home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / TurboTCP 2.0.1 / Terminal pane / CTerminalPane.cp next >
Encoding:
Text File  |  1994-07-03  |  15.5 KB  |  393 lines  |  [TEXT/KAHL]

  1. /*
  2. ** CTerminalPane.cp
  3. **
  4. **    TerminalPane library
  5. **    Terminal display pane
  6. **
  7. **    Copyright © 1993–94, FrostByte Design / Eric Scouten
  8. **
  9. */
  10.  
  11.  
  12. #include "CTerminalPane.h"
  13.  
  14. #include <Events.h>
  15. #include "CBureaucrat.h"
  16. #include "CScrollPane.h"
  17. #include "Global.h"
  18. #include "LongCoordinates.h"
  19. #include "LongQD.h"
  20.  
  21.  
  22.  
  23. extern CBureaucrat* gGopher;
  24.  
  25.  
  26. #define resetInvalsChar 3
  27.  
  28. TCL_DEFINE_CLASS_D1(CTerminalPane, CPanorama)
  29.  
  30.  
  31. //    —— constructor ——
  32.  
  33. /*______________________________________________________________________
  34. **
  35. ** constructors
  36. **
  37. **    Initialize the pane. Nothing special here. Parameters and usage are all the same
  38. **    as for CPanorama.
  39. **
  40. */
  41.  
  42. CTerminalPane::CTerminalPane() : CPanorama()
  43.     { CTerminalPaneX(); }
  44.  
  45. CTerminalPane::CTerminalPane(CView* anEnclosure, CBureaucrat* aSupervisor,
  46.                         short aWidth, short aHeight, short aHEncl, short aVEncl,
  47.                         SizingOption aHSizing, SizingOption aVSizing)
  48.     : CPanorama(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing)
  49.     { CTerminalPaneX(); }
  50.  
  51. void CTerminalPane::ITerminalPane(CView* anEnclosure, CBureaucrat* aSupervisor,
  52.                         short aWidth, short aHeight, short aHEncl, short aVEncl,
  53.                         SizingOption aHSizing, SizingOption aVSizing)
  54. {
  55.     CPanorama::IPanorama(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing);
  56.     if (member(itsEnclosure, CScrollPane))
  57.         ((CScrollPane*) itsEnclosure)->SetSteps(pixelsX, pixelsY);
  58. }
  59.  
  60.  
  61. /*______________________________________________________________________
  62. **
  63. ** CTerminalPaneX (private method)
  64. **
  65. **    Finish initialization for terminal pane.
  66. **
  67. */
  68.  
  69. void CTerminalPane::CTerminalPaneX()
  70.  
  71. {
  72.     LongRect theBounds;
  73.  
  74.     SetLongRect(&theBounds, 0, 0, sizeX, sizeY);
  75.     SetBounds(&theBounds);
  76.     SetCanBeGopher(TRUE);
  77.     SetWantsClicks(TRUE);
  78.     
  79.     if (member(itsEnclosure, CScrollPane))
  80.         ((CScrollPane*) itsEnclosure)->SetSteps(pixelsX, pixelsY);
  81.     
  82.     charsToInvalLine = resetInvalsChar;
  83.     blinkCursor = FALSE;
  84.     cursorVis = TRUE;
  85.     lastCursorCol = lastCursorLine = 0;
  86.     lastCursorTick = 0L;
  87.     disableKeyScroll = FALSE;
  88.     DoClearScreen();
  89. }
  90.  
  91.  
  92. //    —— drawing  ——
  93.  
  94. /*______________________________________________________________________
  95. **
  96. ** Draw
  97. **
  98. **    Draw characters from the theScreen array onto the real screen.
  99. **
  100. **        area (Rect*):    area to be redrawn (in frame coordinates)
  101. **
  102. */
  103.  
  104. void CTerminalPane::Draw(Rect* area)
  105.  
  106. {
  107.     short    left, top, right, bottom;        // char coordinatates of draw region
  108.     short    dLine;                    // where to draw now
  109.     LongRect    theLongArea;                // frame coordinates of region
  110.     LongPt    theLongPt;
  111.     Point        thePoint;
  112.  
  113.  
  114.     // figure draw region
  115.  
  116.     charsToInvalLine = resetInvalsChar;
  117.     QDToFrameR(area, &theLongArea);
  118.     left = (theLongArea.left - offsetX) / pixelsX;
  119.     right = (theLongArea.right -offsetX + 1) / pixelsX;
  120.     top = (theLongArea.top - offsetY) / pixelsY;
  121.     bottom = (theLongArea.bottom -offsetY + 1) / pixelsY;
  122.  
  123.  
  124.     // do range checking
  125.  
  126.     left = TCLMax(left, 0);
  127.     top = TCLMax(top, 0);
  128.     right = TCLMin(right, maxX-1);
  129.     bottom = TCLMin(bottom, maxY-1);
  130.  
  131.  
  132.     // hard-wire for Monaco 9: Mom, don’t look at this code!
  133.  
  134.     TextFont(4);
  135.     TextFace(0);
  136.     TextSize(9);
  137.  
  138.  
  139.     // draw the stuff
  140.  
  141.     if (left <= right) {
  142.         dLine = top;
  143.         while (dLine <= bottom) {
  144.             SetLongPt(&theLongPt, left * pixelsX, dLine * pixelsY);
  145.             FrameToQD(&theLongPt, &thePoint);
  146.             MoveTo(thePoint.h + offsetX, thePoint.v + offsetY + pixelsY-2);
  147.             DrawText(&theScreen[dLine][left], 0, right-left+1);
  148.             dLine++;
  149.         }
  150.     }
  151.  
  152.  
  153.     // check to see if we overwrote the cursor
  154.  
  155.     if ((left <= theColumn) && (right >= theColumn) &&
  156.      (top <= theLine) && (bottom >= theLine) && cursorVis)
  157.          InvertCursor(theColumn, theLine);
  158.     
  159. }
  160.  
  161.  
  162. //    —— blinking cursor support ——
  163.  
  164. /*______________________________________________________________________
  165. **
  166. ** Dawdle
  167. **
  168. **    Blink the cursor if necessary. Cursor blinks at the user-defined rate for insertion point
  169. **    blinking.
  170. **
  171. **        maxSleep (long*):    maximum sleep value, updated if necessary
  172. **
  173. */
  174.  
  175. void CTerminalPane::Dawdle(long* maxSleep)
  176.  
  177. {
  178.     CPanorama::Dawdle(maxSleep);
  179.     if (blinkCursor) {
  180.         *maxSleep = TCLMin(*maxSleep, GetCaretTime());
  181.         if (LMGetTicks() >= lastCursorTick + GetCaretTime()) {
  182.             cursorVis = !cursorVis;
  183.             lastCursorTick = LMGetTicks();
  184.             InvalCharRect(theColumn, theLine, theColumn, theLine);
  185.         }
  186.     }
  187. }
  188.  
  189.  
  190. /*______________________________________________________________________
  191. **
  192. ** BecomeGopher
  193. **
  194. **    Become the gopher (or leave gopher status). All our routine does is force a refresh
  195. **    of the cursor.
  196. **
  197. **        fBecoming (Boolean):        TRUE if becoming gopher
  198. **
  199. **        return (Boolean):        TRUE if successful in changing status
  200. **
  201. */
  202.  
  203. Boolean CTerminalPane::BecomeGopher(Boolean fBecoming)
  204.  
  205. {
  206.     if (!fBecoming)
  207.         cursorVis = TRUE;
  208.     InvalCharRect(theColumn, theLine, theColumn, theLine);
  209.     return CPanorama::BecomeGopher(fBecoming);
  210. }
  211.  
  212.  
  213. /*______________________________________________________________________
  214. **
  215. ** SetBlinking
  216. **
  217. **    Turns on or off cursor blinking.
  218. **
  219. **        blinkMode (Boolean):        TRUE to enable cursor blinking
  220. **
  221. */
  222.  
  223. void CTerminalPane::SetBlinking(Boolean blinkMode)
  224.  
  225. {
  226.     blinkCursor = blinkMode;
  227.     if ((blinkMode)    && (gGopher == this)) {
  228.         lastCursorCol = theColumn;
  229.         lastCursorLine = theLine;
  230.         CursorMoved();
  231.     }
  232.     else {
  233.         cursorVis = TRUE;
  234.         InvalCharRect(theColumn, theLine, theColumn, theLine);
  235.     }
  236. }
  237.  
  238.  
  239. //    —— scrolling ——
  240.  
  241. /*______________________________________________________________________
  242. **
  243. ** ScrollToSelection
  244. **
  245. **    Ensure that the current cursor location is visible.
  246. **
  247. */
  248.  
  249. void CTerminalPane::ScrollToSelection()
  250.  
  251. {
  252.     short    hSpan, vSpan;
  253.     LongRect    topLeftRect, botRightRect;            // top left / bottom right cells of selection
  254.                                             // held over from CTable::ScrollToSelection
  255.                                             // because we might implement character selection later
  256.     LongPt    selPos;
  257.  
  258.  
  259.     // get current window parameters
  260.  
  261.     if (EmptyLongRect(&aperture))                    // nothing selected or nothing visible
  262.         return;
  263.     GetFrameSpan(&hSpan, &vSpan);
  264.     selPos = position;                            // init to current scroll position
  265.  
  266.  
  267.     // figure out where cursor (or selection) is
  268.  
  269.     CalcCharRect(theColumn, theLine, theColumn, theLine, &topLeftRect);
  270.     topLeftRect.left -= offsetX;
  271.     topLeftRect.top -= offsetY;
  272.     topLeftRect.right += offsetX;
  273.     topLeftRect.bottom += offsetY;
  274.     botRightRect = topLeftRect;
  275.             // adapt later for charcter selections
  276.  
  277.  
  278.     // calc vertical scroll
  279.  
  280.     if (topLeftRect.bottom >= position.v + vSpan)        // Is the top of selection below the bottom of frame?
  281.         selPos.v = topLeftRect.bottom - vSpan;
  282.     else if (botRightRect.top < position.v)            // Is the bottom of selection above the top of the frame?
  283.         selPos.v = botRightRect.top;
  284.  
  285.  
  286.     // calc horizontal scroll
  287.  
  288.     if (topLeftRect.right >= position.h + hSpan)        // Is the left edge of selection past the right edge of frame?
  289.         selPos.h = topLeftRect.right - hSpan;
  290.     else if (botRightRect.left < position.h)            // Is the right edge of selection before the left edge of frame?
  291.         selPos.h = botRightRect.left;
  292.  
  293.     if ((selPos.h != position.h) || (selPos.v != position.v))
  294.         ScrollTo(&selPos, TRUE);
  295.  
  296. }
  297.  
  298.  
  299. /*______________________________________________________________________
  300. **
  301. ** DisableKeyScroll
  302. **
  303. **    Turn on or off keyboard scrolling commands.
  304. **
  305. **        disable (Boolean):    TRUE to turn off keyboard scrolling
  306. **
  307. */
  308.  
  309. void CTerminalPane::DisableKeyScroll(Boolean disable)
  310.  
  311. {
  312.     disableKeyScroll = disable;
  313. }
  314.  
  315.  
  316. /*______________________________________________________________________
  317. **
  318. ** DoKeyDown
  319. **
  320. **    Override to enable or disable key scrolling (which is implemented in CPanorama).
  321. **
  322. */
  323.  
  324. void CTerminalPane::DoKeyDown(char theChar, Byte keyCode, EventRecord* macEvent)
  325.  
  326. {
  327.     if (disableKeyScroll)
  328.         CBureaucrat::DoKeyDown(theChar, keyCode, macEvent);
  329.     else
  330.         CPanorama::DoKeyDown(theChar, keyCode, macEvent);
  331. }
  332.  
  333.  
  334. //    —— terminal emulation methods ——
  335.  
  336. /*______________________________________________________________________
  337. **
  338. ** DoClearScreen
  339. **
  340. **    Clear the screen and move the cursor to (0,0).
  341. **
  342. */
  343.  
  344. void CTerminalPane::DoClearScreen()
  345.  
  346. {
  347.     register short x, y;
  348.     
  349.     theLine = theColumn = 0;
  350.     CursorMoved();
  351.  
  352.     for (y = 0; y < maxY; ++y)
  353.         for (x = 0; x < maxX; ++x)
  354.             theScreen[y][x] = ' ';
  355.     Refresh();
  356. }
  357.  
  358.  
  359. /*______________________________________________________________________
  360. **
  361. ** DoWriteChar
  362. **
  363. **    Write a character to the terminal. This method handles *basic* terminal emulation.
  364. **    To provide more sophisticated emulation, override this method.
  365. **
  366. **        theChar (char):        the character to write
  367. **
  368. */
  369.  
  370. void CTerminalPane::DoWriteChar(char theChar)
  371.  
  372. {
  373.  
  374.     // parse a few control characters
  375.  
  376.     switch (theChar) {
  377.  
  378.         case charNUL:
  379.             break;
  380.  
  381.         case charBEL:
  382.             SysBeep(0);
  383.             break;
  384.  
  385.         case charBS:
  386.             if (theColumn > 0)
  387.                 theColumn--;
  388.             CursorMoved();
  389.             break;
  390.  
  391.         case charHT:
  392.             theColumn = ((short) ((theColumn + 7) / 8)) * 8;
  393.             if (the